package com.kk.opengles.screenshotdemo.utils;

import android.app.Service;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.hardware.display.DisplayManager;
import android.hardware.display.VirtualDisplay;
import android.media.Image;
import android.media.ImageReader;
import android.os.Build;
import android.os.IBinder;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.WindowManager;

import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.nio.ByteBuffer;

/**
 * @author wk
 * @date 2025/7/21 13:24
 * @describe
 */
public class ScreenUtils {
    private static final String TAG = "WALX";

    /**
     * 静默截屏，需要权限android.permission.READ_FRAME_BUFFER
     * @return
     */
    public static Bitmap getScreenshot(Context context) {
        WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        if (Build.VERSION.SDK_INT >= 31) {
            //android12以上
            try {
                Class SurfaceControl = Class.forName("android.view.SurfaceControl");
                Class DisplayCaptureArgs = Class.forName("android.view.SurfaceControl$DisplayCaptureArgs");
                Class Builder = Class.forName("android.view.SurfaceControl$DisplayCaptureArgs$Builder");
                IBinder displayToken = (IBinder) SurfaceControl.getMethod("getInternalDisplayToken").invoke(null);
                Constructor CBuilder = Builder.getConstructor(IBinder.class);
                Object mBuilder = CBuilder.newInstance(displayToken);
                Object mDisplayCaptureArgs = Builder.getMethod("build").invoke(mBuilder);
                Method captureDisplay = SurfaceControl.getMethod("captureDisplay", DisplayCaptureArgs);
                captureDisplay.setAccessible(true);
                Object mScreenshotHardwareBuffer = captureDisplay.invoke(null, mDisplayCaptureArgs);
                return (Bitmap) mScreenshotHardwareBuffer.getClass().getMethod("asBitmap").invoke(mScreenshotHardwareBuffer);
            } catch (Throwable e) {
                Log.e(TAG, e.toString());
            }
        } else {
            try {
                Class c = Class.forName("android.view.SurfaceControl");
                Method method = c.getMethod("screenshot", Rect.class, int.class, int.class, int.class);
                return (Bitmap) method.invoke(c, new Rect(), 0, 0, wm.getDefaultDisplay().getRotation());
            } catch (Throwable e) {
                Log.e(TAG, e.toString());
            }
        }
        return null;
    }

    /**
     * 方法二，需要权限android.permission.CAPTURE_VIDEO_OUTPUT和android.permission.CAPTURE_SECURE_VIDEO_OUTPUT
     * @param context
     * @return
     */
    public static Bitmap getScreenshot2(Context context) {
        VirtualDisplay virtualDisplay = null;
        ImageReader reader = null;
        Image image = null;
        try {
            DisplayMetrics metrics = new DisplayMetrics();
            WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
            wm.getDefaultDisplay().getRealMetrics(metrics);
            DisplayManager dm = (DisplayManager) context.getSystemService(Service.DISPLAY_SERVICE);
            reader = ImageReader.newInstance(metrics.widthPixels, metrics.heightPixels, PixelFormat.RGBA_8888, 1);
            int flags = DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR | DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC | DisplayManager.VIRTUAL_DISPLAY_FLAG_PRESENTATION;

            //系统应用
            flags |= DisplayManager.VIRTUAL_DISPLAY_FLAG_SECURE;
//            if (Process.myUid() == Process.SYSTEM_UID) {
//                flags |= DisplayManager.VIRTUAL_DISPLAY_FLAG_SECURE;
//            }
            virtualDisplay = dm.createVirtualDisplay("capture_screen", metrics.widthPixels, metrics.heightPixels, metrics.densityDpi, reader.getSurface(), flags);

            int count = 0;
            while (image == null) {
                Thread.sleep(50);
                image = reader.acquireLatestImage();
                if (++count > 10) {
                    break;
                }
            }
            if (image != null) {
                int width = image.getWidth();
                int height = image.getHeight();
                final Image.Plane[] planes = image.getPlanes();
                final ByteBuffer buffer = planes[0].getBuffer();
                int pixelStride = planes[0].getPixelStride();
                int rowStride = planes[0].getRowStride();
                int rowPadding = rowStride - pixelStride * width;
                Bitmap bitmap = Bitmap.createBitmap(width + rowPadding / pixelStride, height, Bitmap.Config.ARGB_8888);
                bitmap.copyPixelsFromBuffer(buffer);
                return bitmap;
            }
        } catch (Throwable e) {
            Log.e(TAG, e.toString());
        } finally {
            try {
                if (image != null) {
                    image.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            try {
                if (virtualDisplay != null) {
                    virtualDisplay.release();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            try {
                if (reader != null) {
                    reader.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    public static void saveBitmap(Bitmap photo, String file) {
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(file);
            photo.compress(Bitmap.CompressFormat.PNG, 70, fos);
            fos.flush();
            fos.close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }


}
